package com.zhoug.player.exoplayer.v2;

import android.content.Context;
import android.net.Uri;
import android.view.TextureView;

import com.zhoug.player.core.utils.LogUtils;

import androidx.annotation.NonNull;
import androidx.annotation.OptIn;
import androidx.media3.common.C;
import androidx.media3.common.MediaItem;
import androidx.media3.common.PlaybackException;
import androidx.media3.common.Timeline;
import androidx.media3.common.Tracks;
import androidx.media3.common.util.UnstableApi;
import androidx.media3.datasource.DefaultDataSource;
import androidx.media3.datasource.DefaultHttpDataSource;
import androidx.media3.exoplayer.DefaultLivePlaybackSpeedControl;
import androidx.media3.exoplayer.DefaultLoadControl;
import androidx.media3.exoplayer.DefaultRenderersFactory;
import androidx.media3.exoplayer.ExoPlayer;
import androidx.media3.exoplayer.LivePlaybackSpeedControl;
import androidx.media3.exoplayer.hls.DefaultHlsExtractorFactory;
import androidx.media3.exoplayer.hls.HlsMediaSource;
import androidx.media3.exoplayer.source.DefaultMediaSourceFactory;
import androidx.media3.exoplayer.source.MediaSource;
import androidx.media3.exoplayer.trackselection.DefaultTrackSelector;
import androidx.media3.exoplayer.upstream.DefaultLoadErrorHandlingPolicy;
import androidx.media3.exoplayer.util.EventLogger;
import androidx.media3.extractor.ts.DefaultTsPayloadReaderFactory;

/**
 * @author: zhoug
 * @since: 2025-06-20
 */
@Deprecated
@OptIn(markerClass = UnstableApi.class)
public class ZExoPlayer1 {
    private static final String TAG = ">>>ZExoPlayer";

    private ExoPlayer mPlayer;
    /**
     * 上下文
     */
    private Context mContext;
    /**
     * 播放url
     */
    private Uri mPlayUrl;
    /**
     * 视频播放窗口
     */
    private TextureView mTextureView;

    public ZExoPlayer1(@NonNull Context context) {
        this.mContext = context;
    }

    public ExoPlayer getPlayer() {
        return mPlayer;
    }

    /**
     * 视频播放窗口
     *
     * @param textureView
     */
    public void setVideoTextureView(TextureView textureView) {
        mTextureView = textureView;
    }


    /**
     * 播放url
     *
     * @param playUrl
     */
    public void setPlayUrl(Uri playUrl) {
        this.mPlayUrl = playUrl;
    }

    /**
     * 初始化播放器
     */
    private void initPlayer() {
        //直播播放速度控制器
        LivePlaybackSpeedControl livePlaybackSpeedControl = new DefaultLivePlaybackSpeedControl.Builder()
                .setFallbackMaxPlaybackSpeed(1.05f)//设置直播播放时的最大回退播放速度限制
                .build();

        //媒体的缓冲控制器
        DefaultLoadControl loadControl = new DefaultLoadControl.Builder()
                .setBufferDurationsMs(
                        15_000, //最小缓冲时间（毫秒）
                        30_000, //最大缓冲时间（毫秒）
                        500, // 开始播放所需缓冲(毫秒）
                        1_000 //重新缓冲后开始播放所需缓冲(毫秒）
                )
                .setPrioritizeTimeOverSizeThresholds(true) // 关键优化 设置负载控制是否将缓冲区时间约束优先于缓冲区大小约束
                .build();

        //创建播放器实例
        mPlayer = new ExoPlayer.Builder(mContext)
//                .setLivePlaybackSpeedControl(livePlaybackSpeedControl)
                .setLoadControl(loadControl)
                .build();
        mPlayer.addListener(mPlayerListener);
        mPlayer.setVideoTextureView(mTextureView);

        if (LogUtils.isDebug()) {
            mPlayer.addAnalyticsListener(new EventLogger());
        }
    }

    //########################################################################################


    private HlsMediaSource.Factory hlsMediaSourceFactory;
    private MediaItem mediaItem;


    public void startPlay() {
        //创建播放器

        // 创建轨道选择器
        DefaultTrackSelector trackSelector = new DefaultTrackSelector(mContext);
        DefaultTrackSelector.Parameters.Builder builder = trackSelector.buildUponParameters();
        builder.setTrackTypeDisabled(C.TRACK_TYPE_AUDIO, true);
        trackSelector.setParameters(builder);


        DefaultRenderersFactory defaultRenderersFactory = new DefaultRenderersFactory(mContext)
                .setExtensionRendererMode(DefaultRenderersFactory.EXTENSION_RENDERER_MODE_PREFER)
                .forceDisableMediaCodecAsynchronousQueueing();//关闭异步队列


        mPlayer = new ExoPlayer.Builder(mContext)
                .setRenderersFactory(defaultRenderersFactory)
                .setTrackSelector(trackSelector)
                .setSeekForwardIncrementMs(5000)
                .setSeekBackIncrementMs(5000)
                .setLivePlaybackSpeedControl(
                        new DefaultLivePlaybackSpeedControl.Builder()
                                .setFallbackMinPlaybackSpeed(0.80f)//最小播放速度 默认0.97f
                                .setFallbackMaxPlaybackSpeed(1.65f)//最大播放速度 默认 1.03f
                                .setProportionalControlFactor(0.1f)//设置比例控制因子用于计算播放速度调整的比例控制部分 默认0.1f
                                .setMaxLiveOffsetErrorMsForUnitSpeed(500)//当前实时偏移和目标实时偏移之间的默认最大差值 默认20
                                .setTargetLiveOffsetIncrementOnRebufferMs(500) // 遇到重新缓冲时增加延迟 默认500
                                .setMinPossibleLiveOffsetSmoothingFactor(0.99f)//平滑因子.因子越接近1，平滑效果越弱（响应更及时，但可能波动）；因子越小（如0.99），平滑效果越强（响应变慢，但结果更稳定）。 默认0.999f
                                .setMinUpdateIntervalMs(1000)//设置播放速度的最小更新间隔（毫秒），即两次调整播放速度之间的最短时间。默认1_000
                                .build()
                )
                .setLoadControl(
                        new DefaultLoadControl.Builder()
                                .setBufferDurationsMs(
                                        5_000,  // 最小缓冲时间（直播建议 2-5 秒）默认50_000
                                        8_000, // 最大缓冲时间 默认50_000
                                        2000,  // 开始播放前的缓冲 默认 1000
                                        3000   // 重新缓冲后开始播放所需时间 默认2000
                                )
                                .setPrioritizeTimeOverSizeThresholds(true) // 是否根据时间阈值而不是数据量阈值来决定缓冲状态（默认为true）
                                .setTargetBufferBytes(-1) // 目标缓冲区大小（字节），-1表示使用时间阈值（即上面的缓冲时间参数）来控制
                                .setBackBuffer(0, false) // 设置后缓冲区，这里0表示禁用后缓冲（在Media3中，后缓冲区用于保存已经播放过的数据，通常不需要）
                                .build()
                )
                .build();
//        PlayerView
        mPlayer.addListener(new ZDefaultPlayerListener() {
            @Override
            public void onTimelineChanged(Timeline timeline, int reason) {
                if (timeline.isEmpty()) return;
                Timeline.Window window = new Timeline.Window();
                for (int i = 0; i < timeline.getWindowCount(); i++) {
                    timeline.getWindow(i, window);
                    LogUtils.d("onTimelineChanged", "Window[" + i + "]: "
                            + "duration=" + window.getDurationMs()
                            + ", positionInFirstPeriodMs=" + window.getPositionInFirstPeriodMs()
                            + ", currentUnixTimeMs=" + window.getCurrentUnixTimeMs()
                            + ", defaultPositionMs=" + window.getDefaultPositionMs()
                            + ", isLive=" + window.isLive()
                            + ", isDynamic=" + window.isDynamic);
                }
            }

            @Override
            public void onTracksChanged(Tracks tracks) {
                super.onTracksChanged(tracks);

            }
        });
        mPlayer.setVideoTextureView(mTextureView);
        mPlayer.addAnalyticsListener(new EventLogger());
        //媒体项
        MediaItem mediaItem = new MediaItem.Builder()
                .setUri(mPlayUrl)
                .setLiveConfiguration(
                        new MediaItem.LiveConfiguration.Builder()
                                .setTargetOffsetMs(2000)  // 目标直播延迟（毫秒）.设为正数表示期望落后直播边缘的时间
                                .setMinOffsetMs(1000)     // 	允许的最小直播延迟。低于此值时会减速播放避免超过直播前沿
                                .setMaxOffsetMs(15_000)    // 允许的最大直播延迟。超过此值时会加速播放追赶直播边缘。
                                .setMinPlaybackSpeed(0.85f) // 最低播放速度（用于减速调节）
                                .setMaxPlaybackSpeed(1.35f) // 最高播放速度（用于加速追赶）
                                .build()
                )
                .build();



        DefaultHttpDataSource.Factory httpDataSourceFactory = new DefaultHttpDataSource.Factory()
                .setConnectTimeoutMs(5_000)
                .setReadTimeoutMs(10_000)
                .setAllowCrossProtocolRedirects(true)
                .setKeepPostFor302Redirects(true)
                .setTransferListener(new ZDefaultTransferListener());
        //HLS片段提取工厂
        DefaultHlsExtractorFactory defaultHlsExtractorFactory = new DefaultHlsExtractorFactory(
                DefaultTsPayloadReaderFactory.FLAG_ALLOW_NON_IDR_KEYFRAMES, true);


        //hls媒体源工厂
        HlsMediaSource.Factory hlsMediaSourceFactory = new HlsMediaSource.Factory(httpDataSourceFactory)
                .setExtractorFactory(defaultHlsExtractorFactory)
                .setAllowChunklessPreparation(false) // 允许无分片准备
                .setTimestampAdjusterInitializationTimeoutMs(10_000)
                .setUseSessionKeys(false);        // 兼容加密流


        HlsMediaSource mediaSource = hlsMediaSourceFactory.createMediaSource(mediaItem);

        mPlayer.setMediaSource(mediaSource);
        mPlayer.prepare();
        //自动开始播放
        mPlayer.play();
//        mPlayer.seekToDefaultPosition();
        LogUtils.d(TAG, "开始播放");

    }

    /**
     * 开始播放
     */
    public void startPlay1() {
        if (mPlayer == null) {
            //直播播放速度控制器
            LivePlaybackSpeedControl livePlaybackSpeedControl = new DefaultLivePlaybackSpeedControl.Builder()
                    .setFallbackMaxPlaybackSpeed(1.65f)//设置直播播放时的最大回退播放速度限制
                    .build();

            //媒体的缓冲控制器
            DefaultLoadControl loadControl = new DefaultLoadControl.Builder()
                    .setBufferDurationsMs(
                            30_000, //最小缓冲时间（毫秒）
                            600_000, //最大缓冲时间（毫秒）
                            3_000, // 开始播放所需缓冲(毫秒）
                            2_000 //重新缓冲后开始播放所需缓冲(毫秒）
                    )
                    .setPrioritizeTimeOverSizeThresholds(true) //设置负载控制是否将缓冲区时间约束优先于缓冲区大小约束
                    .build();

            DefaultRenderersFactory defaultRenderersFactory = new DefaultRenderersFactory(mContext)
                    //设置如果解码器初始化失败，是否启用回退到低优先级解码器。
                    // 这可能导致使用比主解码器效率更低或更慢的解码器
                    .setEnableDecoderFallback(true)
                    //设置视频渲染器可以尝试无缝加入正在进行的播放的最大持续时间
                    .setAllowedVideoJoiningTimeMs(10000)
                    //允许使用扩展渲染器。扩展渲染器索引在相同类型的核心渲染器之后。因此，偏好第一个合适的渲染器的｛@link TrackSelector｝将倾向于使用核心渲染器而不是扩展渲染器，因为两者都能够播放给定的曲目
                    .setExtensionRendererMode(DefaultRenderersFactory.EXTENSION_RENDERER_MODE_ON);

            //创建播放器实例
            mPlayer = new ExoPlayer.Builder(mContext, defaultRenderersFactory)
//                    .setLivePlaybackSpeedControl(livePlaybackSpeedControl)
//                    .setLoadControl(loadControl)
                    .build();
            mPlayer.addListener(new ZDefaultPlayerListener() {
                @Override
                public void onPlayerError(PlaybackException error) {
                    super.onPlayerError(error);
                   /* if (error.errorCode == PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW) {
                        mPlayer.clearMediaItems();
                        mPlayer.setMediaSource(hlsMediaSourceFactory.createMediaSource(mediaItem));
                        // 遇到直播窗口错误时重新加载
                        mPlayer.prepare(); // 自动重用当前MediaSource恢复播放
                        mPlayer.setPlayWhenReady(true);
                    }*/
                }
            });
            mPlayer.setVideoTextureView(mTextureView);
            mPlayer.addAnalyticsListener(new EventLogger());
        }

        //从网络读取数据工厂
        DefaultHttpDataSource.Factory httpDataSourceFactory = new DefaultHttpDataSource.Factory()
                .setConnectTimeoutMs(5_000)//连接超时
                .setReadTimeoutMs(15_000)//读取超时
                .setAllowCrossProtocolRedirects(true)//跨协议重定向
                .setKeepPostFor302Redirects(true)//
                .setUserAgent("ExoPlayer/Android")
                .setTransferListener(new ZDefaultTransferListener());

        //DefaultDataSource工厂
        DefaultDataSource.Factory defaultDataSourceFactory = new DefaultDataSource.Factory(mContext, httpDataSourceFactory);
        //HLS媒体工厂
        hlsMediaSourceFactory = new HlsMediaSource.Factory(defaultDataSourceFactory)
                .setAllowChunklessPreparation(false)//禁用分块准备（默认false） 强制检查每个片段
//                .setExtractorFactory(new DefaultHlsExtractorFactory(DefaultTsPayloadReaderFactory.FLAG_DETECT_ACCESS_UNITS, false))//HLS片段提取工厂
                .setUseSessionKeys(false)
                .setLoadErrorHandlingPolicy(new DefaultLoadErrorHandlingPolicy(3));//重试次数

        //媒体项
        mediaItem = new MediaItem.Builder()
                .setUri(mPlayUrl)
                .setLiveConfiguration(new MediaItem.LiveConfiguration.Builder()
                        .setTargetOffsetMs(0) //目标偏移量
                        .setMinOffsetMs(0)//最小偏移
                        .setMaxOffsetMs(5000)//最大偏移
                        .setMinPlaybackSpeed(0.65f) // 最低播放速度
                        .setMaxPlaybackSpeed(0.75f) // 最高播放速度
                        .build())
                .build();

        //设置媒体项并准备播放
        mPlayer.setMediaSource(hlsMediaSourceFactory.createMediaSource(mediaItem));
        LogUtils.d(TAG, "开始播放");
        mPlayer.prepare();
        //自动开始播放
        mPlayer.setPlayWhenReady(true);


        /*//从网络读取数据工厂
        DefaultHttpDataSource.Factory httpDataSourceFactory = new ZExoFactory.DefaultHttpDataSourceFactoryBuilder()
                .build();

        //媒体项 MediaItem
        MediaItem mediaItem = new MediaItem.Builder()
                .setUri(mPlayUrl)
                .setLiveConfiguration(new MediaItem.LiveConfiguration.Builder()
                        .setTargetOffsetMs(0) // 从最新点开始播放
                        .setMinOffsetMs(1000)//最小直播偏移（毫秒）
                        .setMaxOffsetMs(5000)//最大直播偏移（毫秒）
                        .setMinPlaybackSpeed(1.0f) // 最低播放速度
                        .setMaxPlaybackSpeed(1.0f) // 最高播放速度
                        .build())
                .build();

        //HLS媒体工厂
        HlsMediaSource.Factory hlsMediaSourceFactory = new ZExoFactory.HlsMediaSourceFactoryBuilder()
                .setDetectAccessUnits(true)
                .setAllowChunklessPreparation(true)
                .create(mContext, httpDataSourceFactory);
        HlsMediaSource mediaSource = hlsMediaSourceFactory.createMediaSource(mediaItem);


        //设置媒体项并准备播放
        mPlayer.setMediaSource(mediaSource);
        LogUtils.d(TAG, "开始播放");
        mPlayer.prepare();
        //自动开始播放（可选）
        mPlayer.setPlayWhenReady(true);*/

    }

    /**
     * 播放监听器
     */
    private ZDefaultPlayerListener mPlayerListener = new ZDefaultPlayerListener() {
        @Override
        public void onPlayerError(PlaybackException error) {
            super.onPlayerError(error);
            if (error.errorCode == PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW) {
                recoverFromBehindLiveWindow();
            }
        }
    };

    /**
     * 直播窗口过期(播放器落后于直播窗口/服务器已删除旧的媒体片段)恢复方法
     */
    private void recoverFromBehindLiveWindow() {
        // 停止播放器
        mPlayer.stop();
        // 重新创建媒体项（强制刷新manifest）
        MediaItem newItem = new MediaItem.Builder()
                .setUri(mPlayUrl + "?t=" + System.currentTimeMillis()) // 添加时间戳避免缓存
                .setLiveConfiguration(new MediaItem.LiveConfiguration.Builder()
                        .setTargetOffsetMs(0) // 从最新点开始播放
                        .setMinOffsetMs(1000)//最小直播偏移（毫秒）
                        .setMaxOffsetMs(5000)//最大直播偏移（毫秒）
                        .setMinPlaybackSpeed(1.0f) // 最低播放速度
                        .setMaxPlaybackSpeed(1.0f) // 最高播放速度
                        .build())
                .build();

        MediaSource mediaSource = new DefaultMediaSourceFactory(mContext)
                .createMediaSource(newItem);

        // 设置新位置（直播边缘）
        mPlayer.setMediaSource(mediaSource);
        mPlayer.prepare();
        mPlayer.setPlayWhenReady(true);
        // 可选：添加用户提示
        LogUtils.d(TAG, "正在同步直播流");

    }

    /**
     * 停止播放
     */
    public void stopPlay() {
        if (mPlayer != null) {
            LogUtils.d(TAG, "停止播放");
            mPlayer.stop();
        }
    }

    /**
     * 暂停播放
     */
    public void pausePlay() {
        if (mPlayer != null) {
            LogUtils.d(TAG, "暂停播放");
            mPlayer.pause();
        }
    }

    /**
     * 恢复播放
     */
    public void resumePlay() {
        if (mPlayer != null) {
            LogUtils.d(TAG, "恢复播放");
            mPlayer.play();
        }
    }

    /**
     * 定位到指定位置播放
     *
     * @param positionMs 毫秒
     */
    public void seekTo(long positionMs) {
        if (mPlayer != null) {
            mPlayer.seekTo(positionMs);
        }
    }

    /**
     * 获取播放进度 单位毫秒
     *
     * @return 播放进度
     */
    public long getCurrentPosition() {
        return mPlayer != null ? mPlayer.getCurrentPosition() : 0;
    }

    /**
     * 释放资源
     */
    public void release() {
        if (mPlayer != null) {
            LogUtils.d(TAG, "release:释放资源:" + mPlayer);
            mPlayer.removeListener(mPlayerListener);
            mPlayer.release();
            mPlayer = null;
        }
    }


}
